﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SC
{
    public class MessagePack
    {
        /// <summary>
        /// 消息类型
        /// </summary>
        public MessageType messageType;
        /// <summary>
        /// 未序列化的原始消息 
        /// </summary>
        public Object messageData;

        public static byte[] headBuf = { 0xAA, 0xAA, 0xAA, 0xAA };//数据头

        public MessagePack()
        {

        }

        private MessagePack(MessageType messageType, Object messageData)
        {
            this.messageType = messageType;
            this.messageData = messageData;
        }

        /// <summary>
        /// 构造传输消息
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static byte[] SerializeObject(SC.MessageType messageType,Object obj)
        {
            byte[] objBuf = Encoding.Default.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(obj));

            
            byte[] msgType = new byte[4];//消息类型
            byte[] lengthBuf = new byte[4];//记录数据长度
            msgType = BitConverter.GetBytes((int)messageType);
            lengthBuf = BitConverter.GetBytes(objBuf.Length);
            //BitConvert.GetBytes(int);
            //BitConvert.ToInt32(byte[], int);


            byte[] sendBuf = new byte[headBuf.Length +msgType.Length+ lengthBuf.Length+objBuf.Length];

            System.Buffer.BlockCopy(headBuf, 0, sendBuf, 0, headBuf.Length);
            System.Buffer.BlockCopy(msgType, 0, sendBuf, 4, msgType.Length);
            System.Buffer.BlockCopy(lengthBuf, 0, sendBuf, 8, lengthBuf.Length);
            System.Buffer.BlockCopy(objBuf, 0, sendBuf, 12, objBuf.Length);

            //SC.MessagePack messagePack = new SC.MessagePack(messageType, sendBuf);

            //byte[] SerializedmessagePack = Encoding.Default.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(messagePack));
            return sendBuf;
        }

        /// <summary>
        /// 转类型
        /// </summary>
        /// <param name="objBuf"></param>
        /// <returns></returns>
        public static T DeserializeObject<T>(byte[] objBuf)
        {
            return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(System.Text.Encoding.Default.GetString(objBuf));
        }

        /// <summary>
        /// 比较两个字节数组是否相等
        /// </summary>
        /// <param name="b1">byte数组1</param>
        /// <param name="b2">byte数组2</param>
        /// <returns>是否相等</returns>
        private static bool BytesEquals(byte[] b1, byte[] b2)
        {
            if (b1.Length != b2.Length) return false;
            if (b1 == null || b2 == null) return false;
            for (int i = 0; i < b1.Length; i++)
                if (b1[i] != b2[i])
                    return false;
            return true;
        }

        /// <summary>
        /// 解析消息 获取消息类型和消息对象字节数组
        /// </summary>
        /// <param name="socketSend"></param>
        /// <param name="msgType"></param>
        /// <param name="objBuf"></param>
        public static void DeserializeObjBuf(System.Net.Sockets.Socket socketSend, out byte[] msgType, out byte[] objBuf)
        {
            #region 处理格式化消息
            byte[] headBuf = new byte[4];//数据头
            msgType = new byte[4];
            byte[] lengthBuf = new byte[4];//记录数据长度
                                           //BitConverter.GetBytes(int);
                                           //BitConverter.ToInt32(byte[], int);
            byte[] structBytes = new byte[12];  //头部标识数据
            int structlength = socketSend.Receive(structBytes, 0, structBytes.Length, System.Net.Sockets.SocketFlags.None);
            System.Buffer.BlockCopy(structBytes, 0, headBuf, 0, headBuf.Length);
            if (BytesEquals(headBuf, SC.MessagePack.headBuf))//数据验证通过
            {
                System.Buffer.BlockCopy(structBytes, 4, msgType, 0, msgType.Length);
                System.Buffer.BlockCopy(structBytes, 8, lengthBuf, 0, lengthBuf.Length);
                int objBufLength = BitConverter.ToInt32(lengthBuf, 0);
                objBuf = new byte[objBufLength];
                int recvedCount = 0;
                while (recvedCount < objBufLength)
                {
                    int count = socketSend.Receive(objBuf, recvedCount, objBufLength-recvedCount, System.Net.Sockets.SocketFlags.None);
                    recvedCount += count;
                }
            }
            else
            {
                objBuf = null;
                System.Threading.Thread.Sleep(100);
            }

            #endregion
        }

    } 
}
